import fx.ResourceFactory;
import javafx.application.Application;
import javafx.collections.ObservableList;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.paint.ImagePattern;
import javafx.scene.shape.Rectangle;
import javafx.stage.Stage;
import lombok.Builder;
import org.jetbrains.annotations.NotNull;

import java.util.HashMap;
import java.util.Map;

public class KeyBoard extends Application {

    private static final int width = 100;
    private static final int height = 100;

    @Override
    public void start(Stage primaryStage) throws Exception {

        Map<KeyCode, KeyEleMapping> keyPressdStateMap = new HashMap<>();


        Pane pane = new Pane();

        ObservableList<Node> children = pane.getChildren();
        children.add(gethBox(keyPressdStateMap));
        children.add(secondHbox(keyPressdStateMap));
        children.add(thirdHbox(keyPressdStateMap));

        pane.requestFocus();
        pane.setPrefSize(1280, 720);
        Scene scene = new Scene(pane);

        scene.setOnKeyPressed(event -> {
            KeyCode code = event.getCode();
            KeyEleMapping keyEleMapping = keyPressdStateMap.get(code);
            if (keyEleMapping != null) {
                keyEleMapping.rectangle.setFill(keyEleMapping.imagePattern);
            }
        });
        scene.setOnKeyReleased(event -> {
            KeyCode code = event.getCode();
            KeyEleMapping keyEleMapping = keyPressdStateMap.get(code);
            if (keyEleMapping != null) {
                keyEleMapping.rectangle.setFill(keyEleMapping.imagePatternN);
            }
        });
        primaryStage.setScene(scene);
        primaryStage.setAlwaysOnTop(true);
        primaryStage.show();
    }

    private HBox secondHbox(Map<KeyCode, KeyEleMapping> keyPressdStateMap) {
        HBox secondHbox = new HBox();
        secondHbox.setLayoutY(120);
        secondHbox.setLayoutX(90);
        secondHbox.setSpacing(20);


        Rectangle a = createKey(KeyCode.A, keyPressdStateMap);
        Rectangle s = createKey(KeyCode.S, keyPressdStateMap);
        Rectangle d = createKey(KeyCode.D, keyPressdStateMap);
        Rectangle f = createKey(KeyCode.F, keyPressdStateMap);
        Rectangle g = createKey(KeyCode.G, keyPressdStateMap);
        Rectangle h = createKey(KeyCode.H, keyPressdStateMap);
        Rectangle j = createKey(KeyCode.J, keyPressdStateMap);
        Rectangle k = createKey(KeyCode.K, keyPressdStateMap);
        Rectangle l = createKey(KeyCode.L, keyPressdStateMap);

        ObservableList<Node> secondHboxChildren = secondHbox.getChildren();
        secondHboxChildren.add(a);
        secondHboxChildren.add(s);
        secondHboxChildren.add(d);
        secondHboxChildren.add(f);
        secondHboxChildren.add(g);
        secondHboxChildren.add(h);
        secondHboxChildren.add(j);
        secondHboxChildren.add(k);
        secondHboxChildren.add(l);
        return secondHbox;
    }

    @NotNull
    private Rectangle createKey(KeyCode keyCode, Map<KeyCode, KeyEleMapping> keyPressdStateMap) {
        Rectangle a = new Rectangle(width, height);
        a.setArcHeight(15);
        a.setArcWidth(15);
        a.setFill(new ImagePattern(ResourceFactory.from(keyCode.getChar() + ".png")));
        keyPressdStateMap.put(keyCode, new KeyEleMapping(new ImagePattern(ResourceFactory.from(keyCode.getChar() + "1.png")), new ImagePattern(ResourceFactory.from(keyCode.getChar() + ".png")), a));
        return a;
    }

    @NotNull
    private HBox gethBox(Map<KeyCode, KeyEleMapping> keyPressdStateMap) {
        HBox firstHbox = new HBox();
        firstHbox.setLayoutX(50);
        firstHbox.setSpacing(20);
        ObservableList<Node> firstHboxChildren = firstHbox.getChildren();

        Rectangle q = createKey(KeyCode.Q, keyPressdStateMap);
        Rectangle w = createKey(KeyCode.W, keyPressdStateMap);
        Rectangle e = createKey(KeyCode.E, keyPressdStateMap);
        Rectangle r = createKey(KeyCode.R, keyPressdStateMap);
        Rectangle t = createKey(KeyCode.T, keyPressdStateMap);
        Rectangle y = createKey(KeyCode.Y, keyPressdStateMap);
        Rectangle u = createKey(KeyCode.U, keyPressdStateMap);
        Rectangle i = createKey(KeyCode.I, keyPressdStateMap);
        Rectangle o = createKey(KeyCode.O, keyPressdStateMap);
        Rectangle p = createKey(KeyCode.P, keyPressdStateMap);

        firstHboxChildren.add(q);
        firstHboxChildren.add(w);
        firstHboxChildren.add(e);
        firstHboxChildren.add(r);
        firstHboxChildren.add(t);
        firstHboxChildren.add(y);
        firstHboxChildren.add(u);
        firstHboxChildren.add(i);
        firstHboxChildren.add(o);
        firstHboxChildren.add(p);
        return firstHbox;
    }

    @NotNull
    private HBox thirdHbox(Map<KeyCode, KeyEleMapping> keyPressdStateMap) {
        HBox firstHbox = new HBox();
        firstHbox.setLayoutX(130);
        firstHbox.setLayoutY(240);
        firstHbox.setSpacing(20);
        ObservableList<Node> firstHboxChildren = firstHbox.getChildren();

        Rectangle z = createKey(KeyCode.Z, keyPressdStateMap);
        Rectangle x = createKey(KeyCode.X, keyPressdStateMap);
        Rectangle c = createKey(KeyCode.C, keyPressdStateMap);
        Rectangle v = createKey(KeyCode.V, keyPressdStateMap);
        Rectangle b = createKey(KeyCode.B, keyPressdStateMap);
        Rectangle n = createKey(KeyCode.N, keyPressdStateMap);
        Rectangle m = createKey(KeyCode.M, keyPressdStateMap);

        firstHboxChildren.add(z);
        firstHboxChildren.add(x);
        firstHboxChildren.add(c);
        firstHboxChildren.add(v);
        firstHboxChildren.add(b);
        firstHboxChildren.add(n);
        firstHboxChildren.add(m);
        return firstHbox;
    }

    @Builder
    private static class KeyEleMapping {
        private ImagePattern imagePattern;
        private ImagePattern imagePatternN;
        private Rectangle rectangle;
    }
}
